// 错误处理
// window.onerror = function(error, url, line) {
// 	alert(error + '\n' + url + ':' + line);
// 	return false;
// };
// 初始化 $
!window.$ && (window.$ = {});
// context 对象
window.$.context = {
    session: {options: {}},
    params: {
        put: function (key, value) {
            !$.context.params.data && ($.context.params.data = {});
            if (typeof key == 'string') {
                $.context.params.data[key] = value;
            } else {
                angular.extend($.context.params.data, key);
            }
            return this;
        },
        get: function (key) {
            !$.context.params.data && ($.context.params.data = {});
            return $.context.params.data[key];
        },
        take: function (key) {
            var value = $.context.params.get(key);
            delete $.context.params.data[key];
            return value;
        },
        remove: function (key) {
            delete $.context.params.data[key];
        }
    },
    rme: function (name) {
        $.context.session && (window.localStorage[name] = angular.toJson($.context.session));
        return this;
    },
    dme: function (name) {
        delete window.localStorage[name];
    },
    open: function (name) {
        var session = window.localStorage[name];
        session && ($.context.session = angular.fromJson(session));
        return this;
    },
    close: function () {
        $.context.session = {};
        $.context.params.data = {};
        return this;
    }
};
/**
 * commons module
 * requirejs: commons.bootstrap.plugin.js || commons.ionic.plugin.js
 */
angular.module('basic.commons', []).directive('bcFocus', function ($timeout, $commons) {
    return function (scope, element) {
        return (element.attr('bc-focus') == 'true' || $commons.getValue(scope, element.attr('bc-focus'))) && $timeout(function () {
                element[0].focus();
            }, 300);
    };
}).directive('bcIntType', function ($commons) { // 只能输入整形: 0123456789
    return function (scope, element) {
        return (element.attr('bc-int-type') == 'true' || $commons.getValue(scope, element.attr('bc-int-type'))) && element.bind('keypress', function (event) { // keypress 事件处理
                var keyCode = event.which;
                if (!(keyCode >= 48 && keyCode <= 57) || (keyCode == 13)) {
                    event.preventDefault();
                    return false;
                } else {
                    return true;
                }
            }).bind('paste', function () { // CTR+V 事件处理
                element.val(element.val().replace(/\D|^0/g, ''));
            }).css('ime-mode', 'disabled'); //CSS设置输入法不可用
    };
}).directive('bcNumberType', function () { // 只能输入数字: 0123456789.
    return function (scope, element) {
        return element.keypress(function (event) { // keypress 事件处理
            var keyCode = event.which;
            if (keyCode == 46) {
                return $(this).val().indexOf('.') == -1;
            } else {
                return (keyCode >= 48 && keyCode <= 57) || (keyCode == 13);
            }
        }).bind('paste', function () { // CTR+V 事件处理
            $(this).val($(this).val().replace(/\D|^0/g, ''));
        }).css('ime-mode', 'disabled'); //CSS设置输入法不可用
    };
}).directive('bcMaxLength', function ($commons) { // 输入字符长度限制，中文算两个字节
    return function (scope, element) {
        var max = parseInt($commons.getValue(scope, element.attr('bc-max-length')) || element.attr('bc-max-length'));
        if (max > 0) {
            return element.bind('keypress', function (event) { // keypress 事件处理
                var len = 0, val = $commons.getValue(scope, element.attr('ng-model')), keyCode = event.which;
                for (var i = 0; val && i < val.length; i++) {
                    if (val[i].match(/[^\x00-\xff]/ig) != null) { //全角
                        len += 2;
                    } else {
                        len += 1;
                    }
                }
                if (!((len < max) || (keyCode == 13))) {
                    event.preventDefault();
                    return false;
                } else {
                    return true;
                }
            }).bind('paste', function () { // CTR+V 事件处理
                var len = 0, val = element.attr('value'), valToUse = '';
                for (var i = 0; i < val.length; i++) {
                    if (val[i].match(/[^\x00-\xff]/ig) != null) { //全角
                        len += 2;
                    } else {
                        len += 1;
                    }

                    if (len > max) {
                        break;
                    }

                    valToUse += val[i];
                }
                element.attr('value', valToUse);
            }).css('ime-mode', 'disabled'); //CSS设置输入法不可用
        }
    };
}).directive('bcImageUpload', function ($timeout, $commons, $state) {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            var attr = $commons.trim(attrs['bcImageUpload']), options = attr && attr.indexOf('{') == 0 ? eval('(' + attr + ')') : $commons.getValue(scope, attr);
            var width = options.width, height = options.height;
            element.bind('change', function (event) {
                $commons.progressbar().show()
                console.log('enter change method..');
                var image = event.currentTarget.files[0];
                if (image) {
                    var reader = new FileReader();
                    reader.onload = function (event) {
                        scope.$apply(function () {
                            console.log('enter reader onload..');
                            scope[options.preview] = event.target.result;
                        });
                    };
                    reader.readAsDataURL(image);
                    var avFile = new AV.File(image.name, image);
                    console.log('begin to call avfile save()..');
                    avFile.save().then(function () {
                        var imageUrl = avFile._url;
                        if (!!width && !!height) {
                            imageUrl = avFile.thumbnailURL(width, height);
                        }
                        $commons.setValue(scope, options.model, imageUrl);
                        if (options.callbackFunc) {
                            scope.$parent[options.callbackFunc]();
                        }
                        console.log('after avfile save()');
                        $commons.progressbar().hide()
                    }, function (error) {
                        alert('上传失败: ' + error.message);
                        $commons.progressbar().hide()
                    });
                } else {
                    $commons.progressbar().hide();
                }
            });
        }
    };
}).filter('isoDateFormat', function () { // 日期格式过滤器
        return function (dateString) {
            if (dateString && dateString.iso) {
                return dateString.iso;
            }
            else
                return '';
        };
    })
    .factory('TokenInterceptor', function ($q, $location) {
        return {
            request: function (config) {
                config.headers = config.headers || {};
                if ($.context.session.token) {
                    config.headers.Authorization = 'Bearer ' + $.context.session.token;
                }
                return config;
            },

            requestError: function(rejection) {
                console.log('...in request error');
                return $q.reject(rejection);
            },

            /* Set Authentication.isAuthenticated to true if 200 received */
            response: function (response) {
                if (response != null && response.status == 200 && $.context.session.token && !$.context.session.isAuthenticated) {
                    $.context.session.isAuthenticated = true;
                    $.context.rme($.context.GLOBAL_SESSION);
                }
                return response || $q.when(response);
            },

            /* Revoke client authentication if 401 is received */
            responseError: function(rejection) {
                if (rejection != null && rejection.status === 401 && ($.context.session.token || $.context.session.isAuthenticated)) {
                    $.context.session.token = null;
                    $.context.session.isAuthenticated = false;
                    $.context.rme($.context.GLOBAL_SESSION);
                    var r = confirm("您当前登录已超时, 请重新登录");
                    if (r == true) {
                        window.location.replace('#/login');
                    } else {
                        console.log('cancle...');
                    }
                }
                return $q.reject(rejection);
            }
        };
    })
    .factory('$commons', function ($http, $timeout, $locale, $ionicLoading) {
        var class2type = {}, toString = class2type.toString, hasOwn = class2type.hasOwnProperty, rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;
        angular.forEach("Boolean Number String Function Array Date RegExp Object Error".split(" "), function (name) {
            class2type["[object " + name + "]"] = name.toLowerCase();
        });
        return {
            // start copy from jquery
            isWindow: function (obj) {
                return obj != null && obj === obj.window;
            },
            type: function (obj) {
                if (obj == null) {
                    return obj + "";
                }
                // Support: Android < 4.0, iOS < 6 (functionish RegExp)
                return typeof obj === "object" || typeof obj === "function" ?
                class2type[toString.call(obj)] || "object" :
                    typeof obj;
            },
            isPlainObject: function (obj) {
                // Not plain objects:
                // - Any object or value whose internal [[Class]] property is not "[object Object]"
                // - DOM nodes
                // - window
                if (this.type(obj) !== "object" || obj.nodeType || this.isWindow(obj)) {
                    return false;
                }
                if (obj.constructor && !hasOwn.call(obj.constructor.prototype, "isPrototypeOf")) {
                    return false;
                }
                // If the function hasn't returned already, we're confident that
                // |obj| is a plain object, created by {} or constructed with new Object
                return true;
            },
            extend: function () {
                var options, name, src, copy, copyIsArray, clone,
                    target = arguments[0] || {},
                    i = 1,
                    length = arguments.length,
                    deep = false;
                // Handle a deep copy situation
                if (typeof target === "boolean") {
                    deep = target;
                    // skip the boolean and the target
                    target = arguments[i] || {};
                    i++;
                }
                // Handle case when target is a string or something (possible in deep copy)
                if (typeof target !== "object" && !angular.isFunction(target)) {
                    target = {};
                }
                // extend jQuery itself if only one argument is passed
                if (i === length) {
                    target = this;
                    i--;
                }
                for (; i < length; i++) {
                    // Only deal with non-null/undefined values
                    if ((options = arguments[i]) != null) {
                        // Extend the base object
                        for (name in options) {
                            src = target[name];
                            copy = options[name];
                            // Prevent never-ending loop
                            if (target === copy) {
                                continue;
                            }
                            // Recurse if we're merging plain objects or arrays
                            if (deep && copy && ( this.isPlainObject(copy) || (copyIsArray = angular.isArray(copy)) )) {
                                if (copyIsArray) {
                                    copyIsArray = false;
                                    clone = src && angular.isArray(src) ? src : [];
                                } else {
                                    clone = src && this.isPlainObject(src) ? src : {};
                                }
                                // Never move original objects, clone them
                                target[name] = this.extend(deep, clone, copy);

                                // Don't bring in undefined values
                            } else if (copy !== undefined) {
                                target[name] = copy;
                            }
                        }
                    }
                }
                // Return the modified object
                return target;
            },
            // Support: Android<4.1, IE<9
            trim: function (text) {
                return text == null ? "" : ( text + "" ).replace(rtrim, "");
            },
            // end copy from jquery
            getValue: function (root, name) {
                if (root) {
                    if (name) {
                        var A = name.indexOf('['), B = name.indexOf('.');
                        if (A == 0) { // [n] || [n].*
                            var end = name.indexOf(']'), pname = name.substring(1, end), cname = name.substring(end + 1);
                            cname.substring(0, 1) == '.' && (cname = cname.substring(1));
                            !isNaN(pname) && (pname = parseInt(pname, 10)); // 假如是数字字符串，转换为数字类型
                            return cname ? this.getValue(root[pname], cname) : root[pname];
                        } else if (A != -1 && B != -1) {
                            if (A < B) { // *[n].*
                                var pname = name.substring(0, A), cname = name.substring(A);
                                return this.getValue(root[pname], cname);
                            } else { // *.*[n]
                                var pname = name.substring(0, B), cname = name.substring(B + 1);
                                return this.getValue(root[pname], cname);
                            }
                        } else if (A == -1 && B != -1) { // *.*
                            var pname = name.substring(0, B), cname = name.substring(B + 1);
                            return this.getValue(root[pname], cname);
                        } else if (A != -1 && B == -1) { // *[n]
                            var pname = name.substring(0, A), cname = name.substring(A);
                            return this.getValue(root[pname], cname);
                        } else {
                            return root[name];
                        }
                    }
                }
            },
            setValue: function (root, name, value) {
                if (root) {
                    if (name) {
                        var A = name.indexOf('['), B = name.indexOf('.');
                        if (A == 0) { // [n] || [n].*
                            var end = name.indexOf(']'), pname = name.substring(1, end), cname = name.substring(end + 1);
                            cname.substring(0, 1) == '.' && (cname = cname.substring(1));
                            !isNaN(pname) && (pname = parseInt(pname, 10)); // 假如是数字字符串，转换为数字类型
                            return cname ? this.setValue(root[pname] || (root[pname] = {}), cname, value) : (root[pname] = value);
                        } else if (A != -1 && B != -1) {
                            if (A < B) { // *[n].*
                                var pname = name.substring(0, A), cname = name.substring(A);
                                return this.setValue(root[pname] || (root[pname] = {}), cname, value);
                            } else { // *.*[n]
                                var pname = name.substring(0, B), cname = name.substring(B + 1);
                                return this.setValue(root[pname] || (root[pname] = {}), cname, value);
                            }
                        } else if (A == -1 && B != -1) { // *.*
                            var pname = name.substring(0, B), cname = name.substring(B + 1);
                            return this.setValue(root[pname] || (root[pname] = {}), cname, value);
                        } else if (A != -1 && B == -1) { // *[n]
                            var pname = name.substring(0, A), cname = name.substring(A);
                            return this.setValue(root[pname] || (root[pname] = {}), cname, value);
                        } else {
                            root[name] = value;
                        }
                    }
                }
            },
            nameOf: function (array, name, value, dest) {
                if (name != undefined && value == undefined) {
                    value = name.name;
                    name = 'name';
                }
                for (var i = 0; array && name && value && i < array.length; i++) {
                    if (array[i][name] == value) {
                        if (dest == undefined) {
                            return array[i];
                        } else {
                            dest.push(array[i]);
                        }
                    }
                }
                return dest;
            },
            assign: function (array, srcname, destname, value) {
                for (var i = 0; array && srcname && destname && i < array.length; i++) {
                    array[i][srcname] != undefined && (value != undefined ? (array[i][destname] = array[i][srcname] = value) : (array[i][destname] = array[i][srcname]));
                }
            },
            wsize: function () {
                var height = 0, width = 0;
                if (typeof (window.innerWidth) == 'number') {
                    height = window.innerHeight;
                    width = window.innerWidth;
                } else if (document.documentElement && (document.documentElement.clientWidth || document.documentElement.clientHeight)) {
                    height = document.documentElement.clientHeight;
                    width = document.documentElement.clientWidth;
                } else if (document.body && (document.body.clientWidth || document.body.clientHeight)) {
                    height = document.body.clientHeight;
                    width = document.body.clientWidth;
                }
                return {width: width, height: height};
            },
            _forId: function (id, name) {
                if (!id || !name) {
                    return name;
                }
                return id + angular.uppercase(name.substring(0, 1)) + name.substring(1, name.length);
            },
            more: function ($scope, options) {
                var id = options && options.id || '', self = this;
                options = this.extend(true, {
                    ajax: {
                        url: '',
                        success: function (results) {
                            options.ajax.prepared && (results = options.ajax.prepared(results));
                            options.ajax.setupRef && self.setupRef(results);
                            for (var i = 0; i < results.length; i++) {
                                $scope[options.results.id].push(results[i]);
                            }
                            $scope[options.firstResult.id] += results.length;
                            options.ajax.onsuccess && options.ajax.onsuccess(results);
                        }
                    },
                    firstResult: {id: this._forId(id, 'firstResult'), value: 0},
                    maxResults: {id: this._forId(id, 'maxResults'), value: 20},
                    results: {id: this._forId(id, 'results')}
                }, options);
                var more = {
                    load: function (ajax) {
                        angular.extend(options.ajax, {
                            data: {
                                firstResult: $scope[options.firstResult.id],
                                maxResults: $scope[options.maxResults.id]
                            }
                        }, ajax);
                        options.ajax.method == 'get' ? self.get(options.ajax) : self.post(options.ajax);
                        return this;
                    },
                    reload: function (ajax) {
                        return this.reset().load(ajax);
                    },
                    reset: function () {
                        $scope[options.firstResult.id] = options.firstResult.value;
                        $scope[options.maxResults.id] = options.maxResults.value;
                        $scope[options.results.id] = [];
                        return this;
                    }
                };

                more.reset();

                return more;
            },
            loading: function (func) {
                var progressbar = this.progressbar().show();
                $timeout(func, 0)['finally'](function () {
                    progressbar.hide();
                });
            },
            progressbar: function () {
                return {
                    show: function () {
                        $ionicLoading.show({template: 'Loading...'});
                        return this;
                    },
                    hide: function () {
                        $ionicLoading.hide();
                        return this;
                    }
                };
            },
            setupRef: function (root, object, attr, value) {
                (arguments.length == 1) && (value = root);
                for (sa in value) {
                    if (sa == '$ref') {
                        object[attr] = eval('root' + value[sa].substring(1));
                        break;
                    } else if (angular.isObject(value[sa])) {
                        this.setupRef(root, value, sa, value[sa]);
                    }
                }
                return root;
            },
            cformat: function (object, fmt) {
                for (var i = 2; i < arguments.length; i++) {
                    var name = arguments[i], date = object ? object[name] : null, value = this.dformat(date, fmt);
                    value && (object[name] = value);
                }
            },
            dformat: function (date, fmt) {
                return date && date.format ? date.format(fmt) : date;
            },
            dparse: function (text, fmt, dd) {
                if (text && text.length == 'yyyy-MM-dd'.length && fmt == 'yyyy-MM-dd') {
                    var date = new Date();
                    date.setFullYear(parseInt(text.substring(0, 4), 10), parseInt(text.substring(5, 7), 10) - 1, parseInt(text.substring(8, 10), 10));
                    return date;
                }
                return dd;
            },
            http: function (options) {
                var progressbar = this.progressbar().show();
                $http(options).success(function () {
                    progressbar.hide();
                    options.success && options.success.apply(this, arguments);
                }).error(function () {
                    progressbar.hide();
                    options.errorText && $ionicPopup.alert({template: options.errorText});
                    options.error && options.error.apply(this, arguments);
                });
            },
            post: function (options) {
                this.http(angular.extend({
                    method: 'post',
                    responseType: 'json',
                    cache: false
                }, options));
            },
            get: function (options) {
                this.http(angular.extend({
                    method: 'get',
                    responseType: 'json',
                    cache: false
                }, options));
            },
            delete: function (options) {
                this.http(angular.extend({
                    method: 'delete',
                    responseType: 'json',
                    cache: false
                }, options));
            },
            upload: function (options) {
                this.http(angular.extend({
                    method: 'post',
                    headers: {'Content-Type': undefined},
                    transformRequest: angular.identity,
                    responseType: 'json'
                }, options));
            },
            imageUploader: function (options) {
                var self = this;
                options.element.change(function (event) {
                    var image = this.files[0];
                    //检查文件格式
                    if (image.type.match('image.*')) {
                        var data = new FormData();
                        data.append("multipartFile", image);
                        self.upload({
                            url: 'upload.view',
                            data: data,
                            success: function (status) {
                                if (status.status) {
                                    if (options.rounded) {
                                        var reader = new FileReader();
                                        reader.onload = function (event) {
                                            options.rounded.attr('src', event.target.result);
                                        };
                                        reader.readAsDataURL(image);
                                    }
                                    options.success && options.success(status);
                                } else {
                                    $ionicPopup.alert({template: status.message});
                                }
                            },
                            errorText: '服务请求错误'
                        });
                    } else {
                        $ionicPopup.alert({template: "上传必须为图片。"});
                    }
                });
            },
            /**
             * 计算两个日期的小时差
             * @param signOffTime leancloud的时间格式或者Date类型 结束时间
             * @param signOnTime leancloud的时间格式 开始时间
             */
            calcHourScape: function (signOffTime, signOnTime) {
                if (!signOffTime || !signOnTime) {
                    return 0;
                } else {
                    return Math.round((((signOffTime.iso ? new Date(signOffTime.iso) : signOffTime) - new Date(signOnTime.iso)) / (1000 * 3600)) * 100) / 100
                }
            }

        };
    });

// 对Date的扩展，将 Date 转化为指定格式的String
// 月(M)、日(d)、小时(h)、分(m)、秒(s)、季度(q) 可以用 1-2 个占位符，
// 年(y)可以用 1-4 个占位符，毫秒(S)只能用 1 个占位符(是 1-3 位的数字)
// 例子：
// (new Date()).Format("yyyy-MM-dd hh:mm:ss.S") ==> 2006-07-02 08:09:04.423
// (new Date()).Format("yyyy-M-d h:m:s.S")      ==> 2006-7-2 8:9:4.18
Date.prototype.format = function (fmt) { //author: meizz
    var o = {
        "M+": this.getMonth() + 1, //月份
        "d+": this.getDate(), //日
        "h+": this.getHours(), //小时
        "m+": this.getMinutes(), //分
        "s+": this.getSeconds(), //秒
        "q+": Math.floor((this.getMonth() + 3) / 3), //季度
        "S": this.getMilliseconds() // 毫秒
    };
    if (/(y+)/.test(fmt)) {
        fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
    }
    for (var k in o) {
        if (new RegExp("(" + k + ")").test(fmt)) {
            fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
        }
    }
    return fmt;
};


verifyPhoneNum = function (phoneNUm)
{
    var telReg = /^1[3|4|5|7|8][0-9]\d{8}$/;
    return telReg.test(phoneNUm);
};

verifyMoney = function (money)
{
    var moneyReg = /^\d+(\.\d*)?$/;
    return moneyReg.test(money);
};

verifyEmail = function (email)
{
    var emailReg = /^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/;
    return emailReg.test(email);
};